﻿using System.Collections.Generic;
using System.Diagnostics;
using HK.Core.Extend;
using HK.Core.GUIEx.Protocol.Attribute;
using HK.Core.Network.Download.Control;
using HK.Core.Network.Download.Protocol.Control;
using HK.Core.Network.Download.Protocol.Data;
using HK.Core.Serializable.Attribute;
using HK.Core.Utils;
using UnityEngine;
using UnityEngine.UI;

#if DOWNLOAD_TEST
using System.IO;
using HK.Core.Network.Download.Data;
#endif

namespace HK.Core.Network.Download.UI
{
    
#if DOWNLOAD_TEST

    public class jabInfo
    {
        public long Size = 0;
        public string url = null;
        public long crc = 0L;
    }
    
    /// <summary>
    /// 下载测试脚本
    /// </summary>
    public class UIDownload : MonoBehaviour
#else
    public abstract class UIDownload : MonoBehaviour
#endif
    {

#if DOWNLOAD_TEST
        [SerializeField, GenericField("下载进度条", null, "请使用Unity原生的Slider组件", (int)GUIOperateOptions.BgGenericField)]
#endif
        protected Slider DownloadBar = null;

#if DOWNLOAD_TEST
        [SerializeField, GenericField("进度状态", null, "当前下载状态描述文本。例如：[80%] 1/20(20.0Mb/1.0Gb) 21.Mb/s (Rest:2m) (Cost:4m)")]
#endif
        protected Text ProgressStatus = null;

#if DOWNLOAD_TEST
        [SerializeField, GenericField("下载状态", null, "在进度条上更新当前下载状态。")]
#endif
        protected Text DownloadTxtStatus = null;
        
#if DOWNLOAD_TEST
        [SerializeField, GenericField("允许后台下载")]
#endif
        protected bool AllowBackground = false;
        
        /// <summary>
        /// 时间监控器
        /// </summary>
        public Stopwatch TimeWatch { get; } = new Stopwatch();
        
        [SerializeField, HideInInspector]
        private int _threaderNum = 5;
        /// <summary>
        /// 线程数
        /// </summary>
        public int ThreaderNum
        {
            get => _threaderNum;
            protected set => _threaderNum = value;
        }

        [SerializeField, HideInInspector]
        private int _retry = 3;
        /// <summary>
        /// 重试次数
        /// </summary>
        public int Retry
        {
            get => _retry;
            protected set => _retry = value;
        }
        
        private DownloadManager _downloadManager = null;

#if DOWNLOAD_TEST
        [SerializeField, GenericField("线程数", null, "仅仅显示用，一般开发时，可以不设定。")]
        private Text _threaderNumTxt = null;
        
        [SerializeField, GenericField("下载状态监视", null, "监视下载状态用。")]
        private Text _downloadState = null;
        
        [SerializeField, GenericField("线程状态")]
        private Text _threaderStatus = null;
        
        [SerializeField, GenericField("使用测试数据", null, "勾选，可使用测试数据进行下载测试。")]
        private bool useDummyData = false;
        
        // 测试数据
        private jabInfo[] jabs = new[]
        {
            new jabInfo { Size =  118999392, crc = 2613697622, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/adv.jab" },
            new jabInfo { Size =  152762379, crc = 1934139685, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/bigFiles/commoneffect/particle/images.jab" },
            new jabInfo { Size =  303182775, crc = 643279957, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/bigFiles/environment/sky_system.jab" },
            new jabInfo { Size =   93112356, crc = 345085285, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/bigFiles/sound/bgm/bgm_menu/story.jab" },
            new jabInfo { Size =  356536843, crc = 4272583947, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/bigFiles/ui/dialog/back.jab" },
            new jabInfo { Size =   69891560, crc = 1649620142, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/bigFiles/video/battle/01-01.jab" },
            new jabInfo { Size =   78677699, crc = 3019413279, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/bigFiles/video/chapter.jab" },
            new jabInfo { Size =   42052986, crc = 339669620, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/commoneffect_1.jab" },
            new jabInfo { Size =   34611862, crc = 1643230614, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/commoneffect_2.jab" },
            new jabInfo { Size =   43617857, crc = 2945002810, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/commoneffect_3.jab" },
            new jabInfo { Size =   44851382, crc = 2180647181, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/commoneffect_4.jab" },
            new jabInfo { Size =   45245816, crc = 1310532948, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/commoneffect_5.jab" },
            new jabInfo { Size =  102224368, crc = 804529351, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_background_1.jab" },
            new jabInfo { Size =   48217065, crc = 3632231253, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_background_2.jab" },
            new jabInfo { Size =   73696413, crc = 117644010, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_background_3.jab" },
            new jabInfo { Size =   27395905, crc = 2503574992, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_background_4.jab" },
            new jabInfo { Size =   28113449, crc = 3020118581, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_background_5.jab" },
            new jabInfo { Size =   51737154, crc = 3334962125, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_mapmodel_1.jab" },
            new jabInfo { Size =   56728832, crc = 3538742399, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_mapmodel_2.jab" },
            new jabInfo { Size =  101453608, crc = 601453400, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_mapmodel_3.jab" },
            new jabInfo { Size =  153574326, crc = 776215385, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_mapmodel_4.jab" },
            new jabInfo { Size =   71347549, crc = 1720900991, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_mapmodel_5.jab" },
            new jabInfo { Size =   84501509, crc = 171349534, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_mapmodel_6.jab" },
            new jabInfo { Size =   75955531, crc = 4157999212, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_mapmodel_7.jab" },
            new jabInfo { Size =   51819809, crc = 1497347313, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_model_1.jab" },
            new jabInfo { Size =   56010281, crc = 3045334486, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_model_2.jab" },
            new jabInfo { Size =   91154644, crc = 918816558, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_model_3.jab" },
            new jabInfo { Size =   62685792, crc = 3929762768, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_model_4.jab" },
            new jabInfo { Size =    3069899, crc = 3704985725, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/e_sky_system.jab" },
            new jabInfo { Size =   66598028, crc = 1664882611, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/enemy_1.jab" },
            new jabInfo { Size =  117932551, crc = 2994422065, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/enemy_2.jab" },
            new jabInfo { Size =   61853644, crc = 1540771843, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/enemy_3.jab" },
            new jabInfo { Size =  209091487, crc = 3328631392, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/environment.jab" },
            new jabInfo { Size =   49549701, crc = 999892523, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/global.jab" },
            new jabInfo { Size =  162467668, crc = 3477456452, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/home_1.jab" },
            new jabInfo { Size =   98657645, crc = 1472138172, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/home_2.jab" },
            new jabInfo { Size =   63635947, crc = 726950094, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/item.jab" },
            new jabInfo { Size =    1729219, crc = 1494743296, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/originpack.jab" },
            new jabInfo { Size =   26367588, crc = 682331873, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/role_1.jab" },
            new jabInfo { Size =   37752552, crc = 1438592836, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/role_2.jab" },
            new jabInfo { Size =   62015048, crc = 104979377, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/role_3.jab" },
            new jabInfo { Size =   55683652, crc = 1484645492, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/role_4.jab" },
            new jabInfo { Size =   29853592, crc = 3942067742, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/role_5.jab" },
            new jabInfo { Size =   23195464, crc = 1477722544, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/role_6.jab" },
            new jabInfo { Size =   55788405, crc = 81202722, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/role_7.jab" },
            new jabInfo { Size =  112754383, crc = 3165187107, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/roleplus_1.jab" },
            new jabInfo { Size =  122978697, crc = 3722688796, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/roleplus_2.jab" },
            new jabInfo { Size =   94586546, crc = 1361605337, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/sound_1.jab" },
            new jabInfo { Size =  108859850, crc = 1076107365, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/sound_2.jab" },
            new jabInfo { Size =   60624633, crc = 2070591329, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/sound_3.jab" },
            new jabInfo { Size =   44855179, crc = 526389265, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/sound_4.jab" },
            new jabInfo { Size =  156716810, crc = 3460627159, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/sound_5.jab" },
            new jabInfo { Size =   59287428, crc = 2158262226, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/spine_1.jab" },
            new jabInfo { Size =   73937615, crc = 2427519877, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/spine_2.jab" },
            new jabInfo { Size =   84661301, crc = 1278105782, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/spine_3.jab" },
            new jabInfo { Size =   90524236, crc = 3951897215, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/spine_4.jab" },
            new jabInfo { Size =   99500010, crc = 264383318, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/ui_1.jab" },
            new jabInfo { Size =  110316340, crc = 1649084749, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/ui_2.jab" },
            new jabInfo { Size =  167460331, crc = 1458399932, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/ui_3.jab" },
            new jabInfo { Size =   75531656, crc = 933669645, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/ui_4.jab" },
            new jabInfo { Size =  102814712, crc = 682351660, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/ui_5.jab" },
            new jabInfo { Size =  167046720, crc = 2159991113, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/video_1.jab" },
            new jabInfo { Size =  128715455, crc = 2077885599, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Asset/video_2.jab" },
            new jabInfo { Size =    2459828, crc = 234869545, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/BinaryConfig/binnaryConfig.jab" },
            new jabInfo { Size =        713, crc = 1886938751, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Config/config.jab" },
            new jabInfo { Size =    1458131, crc = 571161165, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Script/script.jab" },
            new jabInfo { Size =     118027, crc = 1253970257, url = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13/Translate/translate.jab" }
        };

        private string downloadUrlPrefix = "https://eden-resource.gameduchy.com/Dev/IOS/0.8.13";
        private string downloadTmpDir = null;
        private string saveDir = null;

        private string ConvertToPath(string iUrl)
        {
            if (string.IsNullOrEmpty(iUrl) || string.IsNullOrEmpty(downloadUrlPrefix) ||
                !iUrl.StartsWith(downloadUrlPrefix)) return null;

            var urlTmp = iUrl.Substring(downloadUrlPrefix.Length);
            if (urlTmp.StartsWith("/"))
            {
                urlTmp = urlTmp.Substring(1);
            }
            return urlTmp;
        }

        private string ConvertToDownloadPath(string iUrl)
        {
            return Path.Combine(downloadTmpDir, ConvertToPath(iUrl));
        }
        
        private string ConvertToSavePath(string iUrl)
        {
            return Path.Combine(saveDir, ConvertToPath(iUrl));
        }

        protected virtual IList<IDownloadInfo> GenerateDownloadTargets()
        {

            if (useDummyData)
            {
                if (null == jabs || 0 >= jabs.Length) return null;

                var downloadDirs = string.Empty;
                var targets = new List<IDownloadInfo>();
                var count = jabs.Length;
                for (var idx = 0; idx < count; ++idx)
                {
                    var jab = jabs[idx];

                    var downloadPath = ConvertToDownloadPath(jab.url);
                    if(string.IsNullOrEmpty(downloadPath)) continue;
                    var downloadDir = UtilsIo.GetFileDirByPath(downloadPath, true);
                    var exist = Directory.Exists(downloadDir);
                    downloadDirs = string.IsNullOrEmpty(downloadDirs) ? $"{idx}:{downloadDir}({exist})" : $"{downloadDirs}\n{idx}:{downloadDir}({exist})"; 
                    //var savePath = ConvertToSavePath(jab.url);
                    //if(string.IsNullOrEmpty(savePath)) continue;
                    //var saveDir = UtilsIo.GetFileDirByPath(savePath, true);
                
                    var target = DownloadInfo.Create(jab.url, "0.8.13", downloadPath, 
                        saveDir, jab.Size, jab.crc, null);
                
                    targets.Add(target);
                }

                if (!string.IsNullOrEmpty(downloadDirs) && null != _downloadState)
                {
                    _downloadState.text = downloadDirs;
                    _downloadState.color = Color.black;
                }
            
                return targets;
            }

            return null;
        }
        
        public void AddThreaderNum()
        {
            ++_threaderNum;            
            if (null != _threaderNumTxt)
            {
                _threaderNumTxt.text = $"{_threaderNum}";
            }

            StopDownload();
        }
        
        public void SubThreaderNum()
        {
            --_threaderNum;            
            if (null != _threaderNumTxt)
            {
                _threaderNumTxt.text = $"{_threaderNum}";
            }

            StopDownload();
        }
        
        /// <summary>
        /// 当前目标列表
        /// </summary>
        public static IList<IDownloadInfo> CurTargets = null;
        
#else

        protected abstract IList<IDownloadInfo> GenerateDownloadTargets();
        
#endif

        /// <summary>
        /// 下载信息显示选项
        /// </summary>
        /// <returns>信息显示选项</returns>
        protected virtual int GetDownloadDisplayOptions() => (int)UtilsMath.DownloadDisplayOptions.Full;
        
        void Awake()
        {
            
#if DOWNLOAD_TEST
            // 使用测试数据
            if (useDummyData)
            {
                this.Error("StartDownload():{0}", Application.persistentDataPath);
                downloadTmpDir = Path.Combine(Application.persistentDataPath, "Tmp");
                if (!UtilsIo.CheckAndCreateDirByFullDir(downloadTmpDir))
                {
                    this.Error("StartDownload():UtilsIo.CheckAndCreateDirByFullDir():Failed!(Dir:{0})", downloadTmpDir);
                    return;
                }
            
                saveDir = Path.Combine(Application.persistentDataPath, "Res");
                if (!UtilsIo.CheckAndCreateDirByFullDir(saveDir))
                {
                    this.Error("StartDownload():UtilsIo.CheckAndCreateDirByFullDir():Failed!(Dir:{0})", downloadTmpDir);
                    return;
                }
            }
#endif
            _downloadManager = DownloadManager.Create(Retry, ThreaderNum);

#if DOWNLOAD_TEST
            if (null != _threaderNumTxt)
            {
                _threaderNumTxt.text = $"{_threaderNum}";
            }
#endif
            TimeWatch.Start();
        }

        private void OnDisable()
        {
            // 停止下载
            StopDownload();
        }
        
#region Params

        private static System.Object _safeLock = new object();

        /// <summary>
        /// 已下载数量
        /// </summary>
        protected int DownloadedCount { get; private set; } = 0;

        /// <summary>
        /// 下载文件总数
        /// </summary>
        protected int TotalCount { get; private set; } = 0;

        /// <summary>
        /// 已下载大小
        /// <para>* 单位 : Byte</para>
        /// </summary>
        protected long DownloadedSize { get; private set; } = 0L;

        /// <summary>
        /// 下载总大小
        /// <para>* 单位 : Byte</para>
        /// </summary>
        protected long TotalSize { get; private set; } = 0L;
        
        /// <summary>
        /// 耗时
        /// <para>* 单位 : 毫秒</para>
        /// </summary>
        protected long CostTime { get; private set; } = 0L;

        /// <summary>
        /// 下载进度状态
        /// </summary>
        public virtual string DownloadStatus { get; protected set; } = null;

        

        /// <summary>
        /// 计算下载进度状态
        /// </summary>
        /// <param name="oProgress"></param>
        /// <returns></returns>
        protected virtual string CalcProgressStatus(out float oProgress)
        {
            oProgress = 0.0f;
            
            // return UtilsMath.GetDownloadDisplayTxt(
            //     DownloadedCount, TotalCount, DownloadedSize, TotalSize, 
            //     _costTimer.ElapsedMilliseconds, out oProgress, GetDownloadDisplayOptions());
            var downloadSpeed = _downloadManager?.Speed;
            if (null == downloadSpeed) return null;
            
            return UtilsMath.GetDownloadDisplayTxt(
                DownloadedCount, TotalCount, DownloadedSize, TotalSize, 
                downloadSpeed, out oProgress, GetDownloadDisplayOptions());
        }

#endregion
        
#region Download
        
        /// <summary>
        /// 开始下载
        /// </summary>
        public void StartDownload()
        {
            
            var curTargets = GenerateDownloadTargets();
            if (null == curTargets || 0 >= curTargets.Count)
            {
                this.Error("StartDownload():There is no target to download!");
                return;
            }

#if DOWNLOAD_TEST
            CurTargets = curTargets;
#endif
            NeedRefresh = true;
            
            // 开始下载
            if (null == _downloadManager)
            {
                _downloadManager = DownloadManager.Create(Retry, ThreaderNum);
            }
            _downloadManager.StartDownload(curTargets, OnDownloadProgress);
        }

        /// <summary>
        /// 取消下载
        /// </summary>
        public void CancelDownload()
        {
            if (null == _downloadManager)
            {
                this.Error("CancelDownload():The DownloadManager has not been initialized yet");
                return;
            }
            // 开始下载
            _downloadManager?.Cancel();
            _downloadManager = null;
        }
        
        /// <summary>
        /// 暂停下载
        /// </summary>
        public void PauseDownload()
        {
            if (null == _downloadManager)
            {
                this.Error("PauseDownload():The DownloadManager has not been initialized yet");
                return;
            }
            
            // 开始下载
            _downloadManager?.Pause();
        }
        
        /// <summary>
        /// 恢复下载
        /// </summary>
        public void ResumeDownload()
        {
            if (null == _downloadManager)
            {
                this.Error("ResumeDownload():The DownloadManager has not been initialized yet");
                return;
            }
            // 开始下载
            _downloadManager?.Resume();
        }
        
        /// <summary>
        /// 停止下载
        /// </summary>
        public void StopDownload()
        {
            DownloadedCount = 0;
            TotalCount = 0;
            DownloadedSize = 0L;
            TotalSize = 0L;
            UpdateProgress(0.0f);
            if (null != DownloadTxtStatus)
            {
                DownloadTxtStatus.text = "";
            }
            if (null != ProgressStatus)
            {
                ProgressStatus.text = "";
            }
            
            // 停止下载
            _downloadManager?.Dispose();
            _downloadManager = null;
        }
        
        /// <summary>
        /// 下载进度回调
        /// <param name="iDownloadedCount">已下载完成文件数</param>
        /// <param name="iTotalCount">下载文件总数</param>
        /// <param name="iDownloadedSize">已下载文件大小(单位:Byte)</param>
        /// <param name="iTotalSize">下载文件总大小(单位:Byte)</param>
        /// <param name="iCostTime">耗时(单位:毫秒)</param>
        /// <param name="iCurrent">当前完成下载目标</param>
        /// </summary>
        private void OnDownloadProgress(int iDownloadedCount, int iTotalCount,
            long iDownloadedSize, long iTotalSize, long iCostTime, IDownloadInfo iCurrent = null)
        {
            lock (_safeLock)
            {
                DownloadedCount = iDownloadedCount;
                TotalCount = iTotalCount;
                DownloadedSize = iDownloadedSize;
                TotalSize = iTotalSize;
                CostTime = iCostTime;
                
                if (null != iCurrent && !string.IsNullOrEmpty(iCurrent.FileName))
                {
                    var targetDesc = iCurrent.FileName;
                    var targetDataSize = UtilsMath.GetDataDisplaySize(iCurrent.Size);
                    var curCostTime = UtilsTime.ConvertToDisplayTime(iCurrent.CostTime, false, 2);
#if DOWNLOAD_TEST
                    targetDesc = $"{targetDesc}({targetDataSize} +{curCostTime})";
#else
                    targetDesc = $"{targetDesc}({targetDataSize})";
#endif
                    DownloadStatus = targetDesc;
                }
            }
        }
        
#endregion

        /// <summary>
        /// 更新进度信息
        /// </summary>
        /// <param name="iProgress">进度</param>
        protected virtual void UpdateProgress(float iProgress)
        {
            if (null == DownloadBar) return;
            
            DownloadBar.value = iProgress;
        }

        /// <summary>
        /// 更新下载状态
        /// </summary>
        /// <param name="iStatus">状态</param>
        protected virtual void UpdateDownloadStatus(string iStatus)
        {
            if(null == DownloadTxtStatus || string.IsNullOrEmpty(iStatus)) return;
            DownloadTxtStatus.text = iStatus;
        }

        /// <summary>
        /// 更新进度状态
        /// </summary>
        /// <param name="iStatus">状态</param>
        /// <param name="iProgress">进度</param>
        protected virtual void UpdateProgressStatus(string iStatus, float iProgress)
        {
            if (null != ProgressStatus && 1.0f >= iProgress && !string.IsNullOrEmpty(iStatus))
            {
                ProgressStatus.text = iStatus;
                if (1.0f <= iProgress)
                {
                    _downloadManager = null;
                    NeedRefresh = false;
                }
            }
        }

        /// <summary>
        /// 刷新标志位
        /// </summary>
        public bool NeedRefresh { get; protected set; } = true;
        
        /// <summary>
        /// 应用程序暂停
        /// </summary>
        /// <param name="iPause">暂停标志位(true:切到后台; false:切回游戏;)</param>
        protected virtual void OnApplicationPause(bool iPause)
        {
            // 下载不在运行中，则返回
            var executing = _downloadManager?.Executing ?? false;
            if(!executing) return;
            
            this.Error("OnApplicationPause():{0}", iPause ? "切到后台" : "返回游戏");
            if (!AllowBackground)
            {
                
                var paused = _downloadManager?.Paused ?? false;
                // 切到后台
                if (iPause && !paused)
                {
                    // 暂停下载
                    PauseDownload();
                }
                
                if (!iPause && paused)
                {
                    // 恢复下载
                    ResumeDownload();
                }
            }
        }

        /// <summary>
        /// 应用程序退出
        /// <para>* 包含一下情况</para>
        /// <para>  1) 正常退出</para>
        /// <para>  2) 当前应用双击Home，然后Kill(仅iOS有反应，Android无反应)</para>
        /// <para>  3) 跳出当前应用，然后Kill(目前:iOS和Android均无反应)</para>
        /// </summary>
        protected virtual void OnApplicationQuit()
        {
            this.Error("OnApplicationQuit()");
            StopDownload();
        }

        /// <summary>
        /// 更新
        /// </summary>
        protected virtual void Update()
        {
            // 无需刷新
            if(!NeedRefresh) return;
            
            // 计算进度状态信息
            var progressStatus = CalcProgressStatus(out var oProgress);
            // 更新进度信息
            UpdateProgress(oProgress);

            // 更新进度信息
            UpdateProgressStatus(progressStatus, oProgress);

            // 更新下载状态
            UpdateDownloadStatus(DownloadStatus);

#if DOWNLOAD_TEST
            var state = _downloadManager?.State ?? DownloadState.Ok;
            var stateDes = _downloadManager?.StateDes;

            if (DownloadState.Ok != state && null != _downloadState)
            {
                var desTxt = $"{state}";

                if (!string.IsNullOrEmpty(stateDes))
                {
                    desTxt = $"{desTxt} - {stateDes}";
                }
                _downloadState.text = desTxt;
                _downloadState.color = Color.red;
                //this.Error(desTxt);
            }

            if (null != _threaderStatus)
            {
                var runningThreader = _downloadManager?.RunningChildThreaderCount ?? 0;
                var threaderMaxNum = _downloadManager?.ThreaderMaxNun ?? 0;
                var managerRunning = _downloadManager?.Executing ?? false;
                var statusTxt = managerRunning ? "Running" : "Stop";
                statusTxt = $"{statusTxt}({runningThreader}/{threaderMaxNum})";
                _threaderStatus.text = statusTxt;
                _threaderStatus.color = managerRunning ? Color.green : Color.red;
            }
#endif
        }
    }
}
